package com.yizhuoyan.his.serviceimpl.doctor.outpatient;

import com.yizhuoyan.his.algorithm.SnowFlake64Id;
import com.yizhuoyan.his.ao.DocHerbalPrescriptionAo;
import com.yizhuoyan.his.ao.DocPrescriptionAo;
import com.yizhuoyan.his.dao.*;
import com.yizhuoyan.his.dto.DocHerbalPrescriptionDto;
import com.yizhuoyan.his.dto.DocPrescriptionDto;
import com.yizhuoyan.his.entity.*;
import com.yizhuoyan.his.exception.HISDataNotExistsException;
import com.yizhuoyan.his.service.doctor.outpatient.PrescriptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 中草药以及中成药业务层方法实现
 *
 * @author 徐世杰
 */
@Transactional
@Valid
@Service
public class PrescriptionServiceImpl implements PrescriptionService {

    @Autowired
    DocHerbalPrescriptionDao herbalDao;
    @Autowired
    DocHerbalPrescriptionDetailDao herbalDetailDao;
    @Autowired
    DocPrescriptionDao presDao;
    @Autowired
    DocPrescriptionDetailDao presDetailDao;
    @Autowired
    HosDrugsDao drugsDao;


    //                                      中草药处方

    /**
     * 新增中草药处方
     *
     * @param ao
     * @throws Exception
     */
    @Override
    public void addHerbalPrescription(@NotNull DocHerbalPrescriptionAo ao) throws Exception {
        //通过前端传入的药品名称，获得该药品的相应数据
        HosDrugsEntity drugsEntity = drugsDao.selectOne("name", ao.getDrugsName());
        if (drugsEntity == null) {
            throw new HISDataNotExistsException("该药品不存在");
        }
        //主键的生成
        SnowFlake64Id snowFlake64Id = new SnowFlake64Id(15);

        //                              向中草药处方添加数据
        DocHerbalPrescriptionEntity e = new DocHerbalPrescriptionEntity();
        e.setId(snowFlake64Id.nextId());
        e.setCreateDoctorId(ao.getCreateDoctorId());
        //挂号id
        e.setRegistrationRecordId(ao.getRegistrationRecordId());
        //病例id
        e.setMedicalRecordId(ao.getMedicalRecordId());
        e.setAdvice(ao.getAdvice());
        e.setCreateTime(LocalDateTime.now());
        e.setTherapyDetail(ao.getTherapyDetailed());
        e.setUsageWay(ao.getUsageWay());
        e.setFrequency(ao.getFrequency());
        e.setPayNumber(ao.getPayNumber());
        //处方名称
        e.setPrescriptionName(ao.getPrescriptionName());
        e.setPrescriptionType(ao.getPrescriptionType());
        //处方状态
        e.setState(ao.getState());
        e.setTherapy(ao.getTherapy());

        //                              向中草药处方详情添加数据
        DocHerbalPrescriptionDetailEntity detailEntity = new DocHerbalPrescriptionDetailEntity();
        detailEntity.setId(snowFlake64Id.nextId());
        detailEntity.setHerbalprescriptionId(e.getId());
        detailEntity.setDrugId(drugsEntity.getId());
        detailEntity.setPrice((double) drugsEntity.getUnitPrice());
        detailEntity.setFootnote(ao.getFootnote());
        detailEntity.setDosage(ao.getDosage());

        herbalDetailDao.insert(detailEntity);
        herbalDao.insert(e);

    }

    /**
     * 根据id移除中草药处方
     *
     * @param id 通过id获得相应的中草药处方（id为病例id）
     * @throws Exception
     */
    @Override
    public void removeHerbalPrescriptionById(@NotBlank Long id) throws Exception {
        //通过病例id判断相应的处方是否存在(一个病人可以有多个处方)
        List<DocHerbalPrescriptionEntity> entities = herbalDao.selectByMedicalRecordId(id);
        if (entities == null) {
            throw new HISDataNotExistsException("未找到相应的处方");
        }
        for (DocHerbalPrescriptionEntity entity : entities) {
            //获得每个处方的id
            Long entityId = entity.getId();
            herbalDao.delete(entityId);
            //处方id即为处方详情的外键
            herbalDetailDao.deleteByHerbalPrescriptionId(entityId);
        }
    }

    /**
     * 根据id修改中草药处方
     *
     * @param id 通过id获得对应的中草药处方（id为病例id）
     * @param ao 需要修改的参数对象
     * @throws Exception
     */
    @Override
    public void modifyHerbalPrescriptionById(@NotBlank Long id, @NotNull DocHerbalPrescriptionAo ao) throws Exception {
        //通过病例id获得所有的中草药处方
        List<DocHerbalPrescriptionEntity> entities = herbalDao.selectByMedicalRecordId(id);
        if (entities == null) {
            throw new HISDataNotExistsException("处方不存在");
        }

        //获得处方表需要修改的数据
        Map<String, Object> herbalPresMap = new HashMap<>();
        herbalPresMap.put("prescriptionName", ao.getPrescriptionName());
        herbalPresMap.put("prescriptionType", ao.getPrescriptionType());
        herbalPresMap.put("payNumber", ao.getPayNumber());
        herbalPresMap.put("frequency", ao.getFrequency());
        herbalPresMap.put("usageWay", ao.getUsageWay());
        herbalPresMap.put("therapy", ao.getTherapy());
        herbalPresMap.put("therapyDetailed", ao.getTherapyDetailed());
        herbalPresMap.put("advice", ao.getAdvice());
        herbalPresMap.put("state", ao.getState());

        //获得向处方详情表修改的数据
        Map<String, Object> herbalPresDetailMap = new HashMap<>();
        herbalPresDetailMap.put("dosage", ao.getDosage());
        herbalPresDetailMap.put("footnote", ao.getFootnote());

        for (DocHerbalPrescriptionEntity entity : entities) {
            //获得每个处方的id
            Long herbalPrescriptionId = entity.getId();
            if (herbalPresMap.values() != null) {
                herbalDao.update(herbalPrescriptionId, herbalPresMap);
            }
            //通过处方id获得该处方详情
            DocHerbalPrescriptionDetailEntity detailEntity = herbalDetailDao.selectOne("herbalprescription_id", herbalPrescriptionId);
            if (herbalPresDetailMap.values() != null) {
                herbalDetailDao.update(detailEntity.getId(), herbalPresDetailMap);
            }
        }
    }

    /**
     * 根据id查新到中草药处方
     *
     * @param id 通过病例id得到对应的处方
     * @return 返回中草药处方，发送给药房并根据处方发药给患者
     * @throws Exception
     */
    @Override
    public List<DocHerbalPrescriptionDto> queryHerbalPrescriptionById(@NotBlank Long id) throws Exception {
        List<DocHerbalPrescriptionDto> result = new ArrayList<>();
        //通过病例id判断相应的处方是否存在(一个病人可以有多个处方)
        List<DocHerbalPrescriptionEntity> entities = herbalDao.selectByMedicalRecordId(id);
        if (entities == null) {
            throw new HISDataNotExistsException("未找到相应的处方");
        }
        DocHerbalPrescriptionDto dto = new DocHerbalPrescriptionDto();
        for (DocHerbalPrescriptionEntity entity : entities) {
            //获得中草药处方表的主键id
            Long herbalPresId = entity.getId();
            DocHerbalPrescriptionDetailEntity detailEntity = herbalDetailDao.selectOne("herbalprescription_id", herbalPresId);
            //得到药品id
            Long drugId = detailEntity.getDrugId();
            HosDrugsEntity drugsEntity = drugsDao.selectById(drugId);
            //得到药品名称
            dto.setName(drugsEntity.getName());
            dto.setState(entity.getState());
            dto.setPrice(detailEntity.getPrice());
            dto.setPrescriptionType(entity.getPrescriptionType());
            dto.setPayNumber(entity.getPayNumber());
            dto.setFrequency(entity.getFrequency());
            dto.setFootnote(detailEntity.getFootnote());
            dto.setDosage(detailEntity.getDosage());
            dto.setAdvice(entity.getAdvice());
            dto.setTherapyDetail(entity.getTherapyDetail());
            dto.setUsageWay(entity.getUsageWay());
            result.add(dto);
        }
        return result;
    }

    //                                     中成药处方

    /**
     * 新增中成药处方
     *
     * @param ao 需要新增的参数对象
     * @throws Exception
     */
    @Override
    public void addPrescription(DocPrescriptionAo ao) throws Exception {

        SnowFlake64Id snowFlake64Id = new SnowFlake64Id(15);
        HosDrugsEntity drugsEntity = drugsDao.selectOne("name", ao.getDrugsName());
        if (drugsEntity == null) {
            throw new HISDataNotExistsException("该药品不存在");
        }
        //中成药处方
        DocPrescriptionEntity presEntity = new DocPrescriptionEntity();
        presEntity.setId(snowFlake64Id.nextId());
        //处方名称
        presEntity.setName(ao.getName());
        presEntity.setRegistrationRecordId(ao.getRegistrationRecordId());
        presEntity.setMedicalRecordId(ao.getMedicalRecordId());
        presEntity.setCreateTime(LocalDateTime.now());
        presEntity.setCreateDoctorId(ao.getCreateDoctorId());
        presEntity.setState(ao.getState());
        presDao.insert(presEntity);
        //中成药处方详情
        DocPrescriptionDetailEntity presDetailEntity = new DocPrescriptionDetailEntity();
        presDetailEntity.setId(snowFlake64Id.nextId());
        presDetailEntity.setPrescriptionId(presEntity.getId());
        presDetailEntity.setFrequency(ao.getFrequency());
        presDetailEntity.setDrugsId(drugsEntity.getId());
        presDetailEntity.setDosage(ao.getDosage());
        presDetailEntity.setAmount(ao.getAmount());
        presDetailEntity.setState(ao.getState());
        presDetailEntity.setUsageWay(ao.getUsageWay());
        presDetailDao.insert(presDetailEntity);
    }

    /**
     * 删除中成药处方
     *
     * @param id 通过病例id获得相应的中成药处方
     * @throws Exception
     */
    @Override
    public void removePrescriptionById(@NotBlank Long id) throws Exception {
        List<DocPrescriptionEntity> entities = presDao.selectByMedicalRecordId(id);
        if (entities == null) {
            throw new HISDataNotExistsException("数据不存在");
        }
        for (DocPrescriptionEntity entity : entities) {
            Long presId = entity.getId();
            presDao.delete(presId);
            presDetailDao.deleteByPrescriptionId(presId);
        }
    }

    /**
     * 修改中成药处方的数据
     *
     * @param id 通过病例id获得对应的中成药处方
     * @param ao 需要修改的参数对象
     * @throws Exception
     */
    @Override
    public void modifyPrescriptionById(@NotNull Long id, @NotBlank DocPrescriptionAo ao) throws Exception {
        List<DocPrescriptionEntity> entities = presDao.selectByMedicalRecordId(id);
        if (entities == null) {
            throw new HISDataNotExistsException("未找到任何处方");
        }
        //中成药处方表可以修改的
        Map<String, Object> presMap = new HashMap<>();
        presMap.put("name", ao.getName());
        presMap.put("state", ao.getState());

        //中成药处方详情表可以修改的
        Map<String, Object> presDetailMap = new HashMap<>();
        presDetailMap.put("usageWay", ao.getUsageWay());
        presDetailMap.put("dosage", ao.getDosage());
        presDetailMap.put("frequency", ao.getFrequency());
        presDetailMap.put("amount", ao.getAmount());
        presDetailMap.put("state", ao.getState());

        for (DocPrescriptionEntity entity : entities) {
            Long presId = entity.getId();
            if (presMap.values() != null) {
                presDao.update(presId, presMap);
            }
            DocPrescriptionDetailEntity detailEntity = presDetailDao.selectOne("prescription_id", presId);
            if (presDetailMap.values() != null) {
                presDetailDao.update(detailEntity.getId(), presDetailMap);
            }
        }
    }

    /**
     * 查询中成药处方
     *
     * @param id 通过病例id得到对应的处方
     * @return 返回中成药处方，用于发送给药房根据此处方给患者开药
     * @throws Exception
     */
    @Override
    public List<DocPrescriptionDto> queryPrescriptionByIdById(Long id) throws Exception {
        List<DocPrescriptionDto> result = new ArrayList<>();
        List<DocPrescriptionEntity> entities = presDao.selectByMedicalRecordId(id);
        if (entities == null) {
            throw new HISDataNotExistsException("未找到任何处方");
        }
        DocPrescriptionDto dto = new DocPrescriptionDto();
        for (DocPrescriptionEntity entity : entities) {
            Long presId = entity.getId();
            //通过处方id获得处方详情
            DocPrescriptionDetailEntity detailEntity = presDetailDao.selectOne("prescription_id", presId);
            //获得药品的id
            Long drugsId = detailEntity.getDrugsId();
            HosDrugsEntity drugsEntity = drugsDao.selectById(drugsId);

            dto.setUsageWay(detailEntity.getUsageWay());
            dto.setState(detailEntity.getState());
            dto.setPrice(drugsEntity.getUnitPrice());
            dto.setName(drugsEntity.getName());
            dto.setAmount(detailEntity.getAmount());
            dto.setFrequency(detailEntity.getFrequency());
            dto.setDosage(detailEntity.getDosage());
            result.add(dto);
        }
        return result;
    }

}
